import idraw.*;
import geometry.*;
import tester.*;
import java.util.*;
import colors.*;

@Example
class Examples{

	Examples(){}

	WholeGameWorld myInitialWorld = new WholeGameWorld 
	(new Mfmwg (new Posn(100, 100), 500), 
			new ConsLoS (new Star (10, new Posn(20, 20)),
					new ConsLoS(new Star(15, new Posn(30, 30)),
							new ConsLoS(new Star
									(10, new Posn(50, 50)),
									new MtLoS()))));

	void go(){
		this.myInitialWorld.bigBang(200, 300, 0.1);
	}    

	public static void main(String[] argv){
		// construct an instance of a TimerWorld
		Examples w = new Examples();
		// and run the TimerWorld
		w.go();
	}

	Star star1, star2, star3, star4;
	Mfmwg m, genie1;
	MtLoS mt;
	ConsLoS starList, starList2, starList3, starList4;
	
	void initData(){
		star1 = new Star(10, new Posn(5,5));
		star2 = new Star(0, new Posn(10,10));
		star3 = new Star(10, new Posn(100, 300));
		star4 = new Star(10, new Posn(50, 50));

		m = new Mfmwg(new Posn(50, 50), 50);
		genie1 = new Mfmwg(new Posn(60, 60), 0);

		mt = new MtLoS();

		starList = new ConsLoS(star1, mt);
		starList2 = new ConsLoS(star2, starList);
		starList3 = new ConsLoS(star3, starList2);
		starList4 = new ConsLoS(star4, starList3);
	}

	//tests for the hitGroundp method in the Star class.
	@TestMethod
	void testHitGroundp(Tester t){
		initData();
		t.checkExpect(this.star1.hitGroundp(), false);
		t.checkExpect(this.star3.hitGroundp(), true);
		initData();
	}

	//tests the isFoundp and foundStar methods in the star class and the ConsLoS class..
	@TestMethod
	void testFound(Tester t){
		initData();
	    t.checkExpect(star4.isFoundp(m), true);
		t.checkExpect(star4.isFoundp(genie1), false);
		t.checkExpect(starList4.foundStar(m), true);
		t.checkExpect(starList4.foundStar(genie1), false);
		initData();
	}

	//tests the caughtStar method in the ConsLoS class.
	@TestMethod
	void testCaughtStar(Tester t){
		initData();
		t.checkExpect(starList4.caughtStar(m), star4);
		initData();
	}

	//tests the catchStar method in the Mfmwg class.
	@TestMethod
	void testCatchStar(Tester t){
		initData();
		t.checkExpect(m.catchStar(star1), new Mfmwg(m.location, m.fuel + 10));
		initData();
	}  

	// tests the method onTick in all classes that implement it
	// star, world, conslos, genie
	@TestMethod
	void testOnTick(Tester t){
		
		initData();
		
		mt.onTick(m);
		t.checkExpect(mt, new MtLoS());
		
		m.onTick();
		t.checkExpect(m, new Mfmwg(m.location, 45));
		
		starList.onTick(m);
		t.checkExpect(starList, new ConsLoS(new Star(9, new Posn(5, 13)), new MtLoS()));
		
		myInitialWorld.onTick();
		t.checkExpect(myInitialWorld,
				new WholeGameWorld(new Mfmwg (new Posn(100, 100), 495),
						new ConsLoS (new Star (9, new Posn(20, 28)),
								new ConsLoS(new Star(14, new Posn(30, 38)),
										new ConsLoS(new Star (9, new Posn(50, 58)),
												new MtLoS())))));
		
		initData();
		
	}

	//tests the onKeyEvent method in the classes WholeGameWorld and Mfmwg.
	@TestMethod
	void testOnKeyEvent(Tester t){
		
		initData();
		
		myInitialWorld.onKeyEvent("up");
		t.checkExpect(myInitialWorld,
				new WholeGameWorld(new Mfmwg(new Posn(100, 90), 495),
						myInitialWorld.stars));
		
		myInitialWorld.onKeyEvent("down");
		t.checkExpect(myInitialWorld,
				new WholeGameWorld(new Mfmwg(new Posn(100, 100), 495),
						myInitialWorld.stars));
		
		myInitialWorld.onKeyEvent("left");
		t.checkExpect(myInitialWorld,
				new WholeGameWorld(new Mfmwg(new Posn(90, 100), 495),
						myInitialWorld.stars));
		
		myInitialWorld.onKeyEvent("right");
		t.checkExpect(myInitialWorld,
				new WholeGameWorld(new Mfmwg(new Posn(100, 100), 495),
						myInitialWorld.stars));
		
		genie1.onKeyEvent("right");
		t.checkExpect(genie1, new Mfmwg(new Posn(70, 60), 0));
		
		genie1.onKeyEvent("left");
		t.checkExpect(genie1, new Mfmwg(new Posn(60, 60), 0));
		
		genie1.onKeyEvent("up");
		t.checkExpect(genie1, new Mfmwg(new Posn(60, 50), 0));
		
		genie1.onKeyEvent("down");
		t.checkExpect(genie1, new Mfmwg(new Posn(60, 60), 0));
		
		initData();
	}

	//tests the makeStar event in the Star class.
	@TestMethod
	void testMakeStar(Tester t){
		
		initData();
		
		t.checkNumRange(star1.makeStar().location.x, 0, 200);
		t.checkExpect(star1.makeStar().location.y, 5);
		t.checkNumRange(star1.makeStar().span, 0, 35);
		
		initData();
	}
}
